package yufa;

import cifa.*;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

/**
 * @创建人 MBY381
 * @创建时间 2022/6/25 14:34
 * @描述 暂无
 */
public class SyntaxAnalysis {
    private String path;
    private CIFFAAnalysis analyser;
    private Pair tuple;
    private int whileNum = 0;
    private int complexNum = 0;
    private int ifNum = 0;
    private boolean flag = false;
    private List<Pair> tupleList;
    private List<CharMark> markTable;
    private List<CharMark> constTable;

    public List<Pair> getTupleList() {
        return tupleList;
    }

    public List<CharMark> getMarkTable() {
        return markTable;
    }

    public List<CharMark> getConstTable() {
        return constTable;
    }

    public SyntaxAnalysis(){
        super();
    }

    public SyntaxAnalysis(String path){
        super();
        this.path = path;
        this.tupleList = new ArrayList<Pair>();
    }

    //获取下一个二元组
    private void advance(){
        try {
            tuple = analyser.analysis();
            if(tuple!=null)
                tupleList.add(tuple);
        } catch (NoteException | DigitException | WordException e) {
            e.printStackTrace();
        }
    }


    private void Sen() throws SyntaxException{
        if(tuple!=null){
            //定义语句
            if(tuple.getFirst()==4){
                defineSen();
                System.out.println("定义语句");
            }
            //赋值语句
            else if(tuple.getFirst()==14){
                assignSen();
                System.out.println("赋值语句");
            }
            //循环语句
            else if(tuple.getFirst()==12){
                whileNum++;
                System.out.println("循环语句"+whileNum+"层开始");
                whileSen();
                System.out.println("循环语句"+whileNum+"层结束");
                whileNum--;
            }
            //复合语句
            else if(tuple.getFirst()==2){
                complexNum++;
                System.out.println("复合语句"+complexNum+"层开始");
                complexSen();
                System.out.println("复合语句"+complexNum+"层结束");
                complexNum--;
            }
            //分支语句
            else if(tuple.getFirst()==9){
                ifNum++;
                System.out.println("分支语句"+ifNum+"层开始");
                branchSen();
                System.out.println("分支语句"+ifNum+"层结束");
                ifNum--;
            }
            //结束语句
            else if(tuple.getFirst()==21){
                endSen();
                System.out.println("结束");
            }
            //空语句
            else if(tuple.getFirst()==23){
                advance();
                System.out.println("空语句");
            }
            //非法语句开头
            else {
                throw new SyntaxException(analyser.getLineNum(), analyser.getColNum()-1,"非法语句");
            }
        }
    }

    //进入定义语句
    private void defineSen() throws SyntaxException{
        advance();
        if(tuple!=null&&tuple.getFirst()==5){
            advance();
            boolean flag = true;
            while(tuple!=null&&tuple.getFirst()==14){
                advance();
                if(tuple!=null&&tuple.getFirst()==20){ //如果是逗号
                    advance();
                    continue;
                }else if(tuple!=null&&tuple.getFirst()==23){  //如果是分号
                    flag = false;
                    advance();
                    break;
                }else throw new SyntaxException(analyser.getLineNum(), analyser.getColNum()-1,"定义语句错误！");
            }
            if(flag) throw new SyntaxException(analyser.getLineNum(), analyser.getColNum()-1,"定义语句错误！");
        }else throw new SyntaxException(analyser.getLineNum(), analyser.getColNum()-1,"定义语句错误！");
    }

    //进入算数表达式
    private void computeSen() throws SyntaxException{
        computeSenF();
        computeSenE();
    }
    private void computeSenF() throws SyntaxException{
        if(tuple!=null&&(tuple.getFirst()==14||tuple.getFirst()==15)){
            advance();
        }
        else if(tuple!=null&&tuple.getFirst()==18){
            advance();
            computeSen();
            if(tuple!=null&&tuple.getFirst()==19)
                advance();
            else throw new SyntaxException(analyser.getLineNum(), analyser.getColNum()-1,"表达式错误！");
        }
        else throw new SyntaxException(analyser.getLineNum(), analyser.getColNum()-1,"表达式错误！");

    }
    private void computeSenE() throws SyntaxException{
        if(tuple!=null&&(tuple.getFirst()==16||tuple.getFirst()==17||tuple.getFirst()==30||tuple.getFirst()==31)){
            advance();
            computeSenF();
            computeSenE();
        }
    }

    //进入赋值语句
    private void assignSen() throws SyntaxException{
        advance();
        if(tuple!=null&&tuple.getFirst()==22){
            advance();
            computeSen();
            if(tuple!=null&&tuple.getFirst()==23){
                advance();
            } else throw new SyntaxException(analyser.getLineNum(), analyser.getColNum()-1,"赋值语句错误！") ;
        }
        else throw new SyntaxException(analyser.getLineNum(), analyser.getColNum()-1,"赋值语句错误！") ;
    }


    //进入布尔表达式
    private void boolSen() throws SyntaxException{
        boolSenM();
        if(tuple!=null&&(tuple.getFirst()==6||tuple.getFirst()==7)){
            advance();
            boolSen();
        }
    }
    private void boolSenM() throws SyntaxException{
        if(tuple!=null&&tuple.getFirst()==8){
            advance();
            if(tuple!=null&&tuple.getFirst()==18){
                advance();
                boolSen();
                if(tuple!=null&&tuple.getFirst()==19)
                    advance();
                else throw new SyntaxException(analyser.getLineNum(), analyser.getColNum()-1,"布尔表达式错误！") ;
            }
            else throw new SyntaxException(analyser.getLineNum(), analyser.getColNum()-1,"布尔表达式错误！") ;

        }
        else {
            computeSen();
            if(tuple!=null&&tuple.getFirst()>=24&&tuple.getFirst()<=29){
                advance();
                computeSen();
            }else throw new SyntaxException(analyser.getLineNum(), analyser.getColNum()-1,"布尔表达式错误！") ;

        }
    }

    //进入循环语句
    private void whileSen() throws SyntaxException{
        advance();
        boolSen();
        if(tuple!=null&&tuple.getFirst()==13){
            advance();
            Sen();
        }
        else throw new SyntaxException(analyser.getLineNum(), analyser.getColNum()-1,"While语句错误！");
    }

    //进入复合语句
    private void complexSen() throws SyntaxException{
        int tempLine = analyser.getLineNum();
        int tempCol = analyser.getColNum()-1;
        advance();
        while(tuple!=null&&tuple.getFirst()!=3){
            Sen();
        }
        if(tuple!=null&&tuple.getFirst()==3){
            advance();
        }else throw new SyntaxException(tempLine,tempCol,"复合语句无end！");

    }

    //进入分支语句
    private void branchSen() throws SyntaxException{
        advance();
        boolSen();
        if(tuple!=null&&tuple.getFirst()==10){
            advance();
            Sen();
            if(tuple!=null&&tuple.getFirst()==11){
                advance();
                Sen();
            }
        }
        else throw new SyntaxException(analyser.getLineNum(), analyser.getColNum()-1,"If语句错误！");

    }


    private void endSen() throws SyntaxException{
        advance();
        if(tuple!=null) throw new SyntaxException(analyser.getLineNum(), analyser.getColNum()-1,"结束符 . 后不可再写入内容");
        else flag = true;
    }

    //处理
    public void process(){
        BufferedReader reader =null;
        try {
            reader = new BufferedReader(new InputStreamReader(new FileInputStream(path)));
            analyser = new CIFFAAnalysis(reader);
            //重置endFlag
            flag = false;
            //分析一开始的程序名
            boolean continueFlag = false;
            advance();
            if(tuple!=null&&tuple.getFirst()==1){
                advance();
                if(tuple!=null&&tuple.getFirst()==14){
                    advance();
                    if(tuple!=null&&tuple.getFirst()==23){
                        advance();
                        continueFlag = true;
                        System.out.println("程序");
                    }
                }
            }

            if(continueFlag){
                while(tuple!=null){
                    Sen();
                }
                if(!flag) throw new SyntaxException(analyser.getLineNum(), analyser.getColNum()-1,"无结束符 .");
                else {
                    markTable = analyser.getMarkTable();
                    constTable = analyser.getConstTable();
                }
            }else throw new SyntaxException(analyser.getLineNum(), analyser.getColNum()-1,"程序定义错误！");

        } catch (Exception e) {
            System.out.println(e);
        }finally{
            try {
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

}
